package com.hu.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.log4j.Logger;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Set;

public class SeleniumUtil {

    private WebDriver driver;
    private Wait<WebDriver> wait;
    private JavascriptExecutor executor;

    private Logger logger = Logger.getLogger(SeleniumUtil.class);
    private double sleepTime;


    public SeleniumUtil() {
    }

    public SeleniumUtil(WebDriver driver, Wait<WebDriver> wait) {
        this.driver = driver;
        this.wait = wait;
        this.executor = (JavascriptExecutor)driver;
        sleepTime = 1;
    }

    public static SeleniumUtil getInstance(WebDriver driver, Wait<WebDriver> wait){
        return new SeleniumUtil(driver,wait);
    }

    public void clickElement(By by){

        try{
            WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
            element.click();
            sSleep(sleepTime);
        }catch (Exception e){
            clickElementByScript(by);
        }

    }

    public void clickExitsElement(By by,int waitTime){

        try {
            WebDriverWait wait1 = new WebDriverWait(driver, waitTime);
            WebElement element = wait1.until(ExpectedConditions.presenceOfElementLocated(by));
            element.click(); sSleep(sleepTime);
        }catch (Exception e){}
    }


    public void clickElementIfExist(By by){
        try{
            WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(by));


            element.click();
            sSleep(sleepTime);
        }catch (Exception e){}

    }

    public void clickElement(WebElement webElement){
        try{
            webElement.click();
            sSleep(sleepTime);

        }catch (Exception e){
            clickElementByScript(webElement);
        }

    }

    public void clickElementByScript(By by){
        WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
        executor.executeScript("arguments[0].click();", element);
        sSleep(sleepTime);
    }

    public void clickElementByScript(WebElement webElement){
        executor.executeScript("arguments[0].click();", webElement);
        sSleep(sleepTime);
    }


    public void sSleep(double sec){
        try {
            Thread.sleep((long) (sec* 1000L));
        } catch (InterruptedException e) {
            logger.error("暂停报错");
            logger.error(e.getMessage());
        }
    }

    public void inputElement(WebElement element, String str) {
        clear(element);
        element.sendKeys(str);
        sSleep(sleepTime);
    }

    public void inputElement(By by, String str) {
        WebElement element = getElement(by);
        clear(element);
        element.sendKeys(str);
        sSleep(sleepTime);
    }

    public void inputElementByScript(By by, String str) {
        WebElement element = getElement(by);
        executor.executeScript("arguments[0].value = arguments[1];", element, str);
        sSleep(sleepTime);
    }

    public void clear(WebElement input) {
        // 将光标移动到输入框末尾
        input.sendKeys(Keys.END);

        while (!input.getAttribute("value").equals("")) {
            input.sendKeys(Keys.BACK_SPACE);
        }
    }

    public WebElement getElement(By by){
        try {
            return wait.until(ExpectedConditions.presenceOfElementLocated(by));
        }catch (Exception e){
            return null;
        }
    }
    public WebElement getElement(By pBy,By by){
        return wait.until(ExpectedConditions.presenceOfElementLocated(pBy)).findElement(by);
    }

    public WebElement getElement(By pBy,By by,int idx){
        List<WebElement> elements = wait.until(ExpectedConditions.presenceOfElementLocated(pBy)).findElements(by);
        return elements.get(idx);
    }

    public WebElement getElement(By by,int idx){
        List<WebElement> elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
        return elements.get(idx);
    }

    public List<WebElement> getElements(By by){
        try {
            return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
        }catch (Exception e){
            return new ArrayList<>();
        }
    }

    public List<WebElement> getElements(By by,int minLimit,int timeout){
        List<WebElement> elements = new ArrayList<>();
        try {
            for (int i = 0; i < timeout; i++) {
                elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
                if(elements.size() >= minLimit){
                    break;
                }
            }
            return elements;
        }catch (Exception e){
            return new ArrayList<>();
        }

    }

    public void clickElement(By by,boolean returnMain){
        String mainWindowHandle = driver.getWindowHandle();
        Set<String> allWindowHandles = driver.getWindowHandles();

        // 切换到modal窗口
        for (String handle : allWindowHandles) {
            if (!handle.equals(mainWindowHandle)) {
                driver.switchTo().window(handle);
                break;
            }
        }

        clickElement(by);

        if(returnMain){
            driver.switchTo().window(mainWindowHandle);
        }

        sSleep(sleepTime);
    }

    public void setSleepTime(double sleepTime) {
        this.sleepTime = sleepTime;
    }

    public static int verificationCodeRecognition(String base64){
        try {
            // 需要发送POST请求的URL地址
            String url = "http://www.fdyscloud.com.cn/tuling/predict";

            // 创建URL对象
            URL obj = new URL(url);

            // 打开HTTP连接并返回HttpURLConnection对象
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();

            // 设置请求方法为POST
            con.setRequestMethod("POST");

            // 设置请求头部信息（如：内容类型、用户代理等）
            con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            con.setRequestProperty("User-Agent", "Mozilla/5.0");

            // 设置是否向HttpURLConnection输出，因为这是POST请求，参数要放在HTTP正文内，因此需要设为true
            con.setDoOutput(true);

            // 构建要发送的JSON参数
            String username = "sjy1998";
            String password = "199891";
            String ID = "23739327";

            String jsonInputString = String.format(
                    "{\"username\":\"%s\", \"password\":\"%s\", \"ID\":\"%s\", \"b64\":\"%s\", \"version\":\"3.1.1\"}",
                    username, password, ID, base64);

            // 获取HttpURLConnection的输出流，用于发送POST请求参数
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());

            // 将JSON参数写入输出流
            wr.write(jsonInputString.getBytes(StandardCharsets.UTF_8));

            // 关闭输出流
            wr.flush();
            wr.close();

            // 获取服务器响应的状态码
            int responseCode = con.getResponseCode();

            // 读取服务器响应内容
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }

            // 关闭输入流
            in.close();

            // 输出服务器响应结果
            System.out.println("Response Code: " + responseCode);
            System.out.println("Response Content: " + response.toString());
            if(responseCode == 200){
                JSONObject jsonObject = JSONUtil.parseObj(response.toString());
                return jsonObject.getJSONObject("data").getInt("距离");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 1;
    }

    public static String ImageToBase64(String path) {
        try {
            // 读取图片文件
            BufferedImage image = ImageIO.read(new File(path));

            // 创建一个字节数组输出流，用于存储图片的字节数据
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            // 将图片写入字节数组输出流（这里以 png 格式为例，你也可以使用其他格式，如 JPEG）
            ImageIO.write(image, "png", outputStream);

            // 将字节数组转换为 Base64 编码的字符串

            // System.out.println(base64Image);
            // 输出 Base64 编码的字符串
            return Base64.getEncoder().encodeToString(outputStream.toByteArray());

        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }


    public static void pictureStitching(String path1,String path2,String targetPath){
        // 读取图片
        List<BufferedImage> images = new ArrayList<>();
        try {
            images.add(ImageIO.read(new File(path1)));
            images.add(ImageIO.read(new File(path2)));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 计算拼接后的图片大小
        int width = 0;
        int height = 0;
        for (BufferedImage image : images) {
            width = Math.max(width, image.getWidth());
            height += image.getHeight();
        }

        // 创建拼接后的图片
        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        // 绘制图片
        Graphics2D g2d = result.createGraphics();
        int y = 0;
        for (BufferedImage image : images) {
            g2d.drawImage(image, 0, y, null);
            y += image.getHeight();
        }
        g2d.dispose();

        // 保存拼接后的图片
        try {
            ImageIO.write(result, "png", new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void base64SavePath(String base64,String savePath){
        // 将 Base64 编码转换为字节数组
        byte[] imageBytes = Base64.getDecoder().decode(base64);

        // 指定文件路径和文件名
        File file = new File(savePath);

        // 将字节数组写入文件
        try (FileOutputStream outputStream = new FileOutputStream(file)) {
            outputStream.write(imageBytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
